package com.company.service.impl;

import com.company.bean.CheckField;
import com.company.bean.CheckResult;
import com.company.service.CheckFormatService;
import org.apache.commons.lang3.StringUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * @author
 * @Date: 2021/1/23 18:26
 */
public class CheckFormatServiceImpl implements CheckFormatService {

    private static ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    private static final String OUT_TYPE = "外访";
    private static final String CALL_TYPE = "电话催收";
    // 通话情况 -- 1 -- 无法接通
    private static final String TURN_OFF_CONNECTION = "1";
    // 通话情况 -- 2 -- 接通
    private static final String TURN_ON_CONNECTION = "2";
    private static final String COMMA = ",";
    private static final String I_SLASH = "/";
    private static final String SLASH = "\\";

    @Override
    public String checkField(Integer count, CheckField checkField, CheckResult checkResult) {
        List<String> validates = validate(checkField);
        String checkString;
        StringBuffer checkStringBuffer = new StringBuffer();
        for (String validate : validates) {
            checkStringBuffer.append(COMMA).append(validate);
        }
        checkString = checkStringBuffer.toString();
        checkString = cascadeCheck(checkField, checkString, checkResult);
        if (StringUtils.isNotBlank(checkString)) {
            checkString = "第" + count + "行" + checkString;
            System.out.println(checkString);
            checkResult.setInCorrectRecordNum(checkResult.getInCorrectRecordNum() + 1);
        }
        return checkString;
    }

    /**
     * 进行级联校验
     *
     * @param checkField
     * @param checkString
     * @param checkResult
     * @return
     */
    private String cascadeCheck(CheckField checkField, String checkString, CheckResult checkResult) {
        String type = checkField.getType().trim();
        String comId = checkField.getCompId();
        String callInfo = checkField.getCallInfo();
        String rTime = checkField.getRTime();
        String telNum = checkField.getTelNum();
        String source = checkField.getSource();
        String regexp_14 = "\\d{14}";
        String regexp_15 = "\\d{0,15}$";
        StringBuffer buffer = new StringBuffer(checkString);
        if (StringUtils.isNotBlank(type)) {
            if (type.equals(CALL_TYPE)) {
                String callNum = checkField.getCallNum();
                String rEndTime = checkField.getREndTime();
                String callType = checkField.getCallType();
                checkNumFormat(buffer, regexp_15, telNum, "被叫电话号码不正确:需为小于15位的纯数字");
                checkNumFormat(buffer, regexp_15, callNum, "主叫号码不正确:需为小于15位的纯数字");
                checkNumFormat(buffer, regexp_14, rTime, "呼叫时间不正确:需要14位纯数字");
                checkNumFormat(buffer, regexp_14, rEndTime, "呼叫结束时间不正确:需要14位纯数字");
                if (StringUtils.isBlank(callType)) {
                    buffer.append(COMMA).append("通话类型格式不正确：呼入/呼出");
                }
                // 催收方式为【电话催收】时，号码来源不可为空
                if (StringUtils.isBlank(source)) {
                    buffer.append(COMMA).append("号码来源不可为空");
                }
                // 催收方式为【电话催收】时，通话情况不可为空
                if (StringUtils.isBlank(callInfo)) {
                    buffer.append(COMMA).append("通话情况不可为空");
                } else if (!TURN_OFF_CONNECTION.equals(callInfo) && !TURN_ON_CONNECTION.equals(callInfo)) {
                    buffer.append(COMMA).append("通话情况格式不正确:1 or 2");
                }
                // 催收方式为【电话催收】时，被叫电话号码不可为空
                if (StringUtils.isBlank(telNum)) {
                    buffer.append(COMMA).append("被叫号码不可为空");
                }
                // 催收方式为【电话催收】时，主叫号码不可为空
                if (StringUtils.isBlank(callNum)) {
                    buffer.append(COMMA).append("主叫号码不可为空");
                }
                // 催收方式为【电话催收】时，呼叫时间不可为空
                if (StringUtils.isBlank(rTime)) {
                    buffer.append(COMMA).append("呼叫时间不可为空");
                }
                // 催收方式为【电话催收】时，呼叫结束时间不可为空
                if (StringUtils.isBlank(rEndTime)) {
                    buffer.append(COMMA).append("呼叫结束时间不可为空");
                }
            } else if (type.equals(OUT_TYPE)) {
                String address = checkField.getAddress();
                if (StringUtils.isBlank(address)) {
                    buffer.append(COMMA).append("外访地址不可为空");
                }
            }
        }
        if (StringUtils.isNotBlank(callInfo) && TURN_ON_CONNECTION.equals(callInfo)) {
            checkResult.setSoundRecordNum(checkResult.getSoundRecordNum() + 1);
            String rName = checkField.getRName();
            String rPath = checkField.getRPath();
            String callDay = null;
            String callDate = null;
            String callYM = null;
            if (StringUtils.isNotBlank(rTime)) {
                callDay = rTime.substring(0, 8);
                callDate = rTime;
                callYM = rTime.substring(0, 6);
            }
            String checkPath = new StringBuffer(I_SLASH).append(comId).append(I_SLASH)
                    .append(callYM).append(I_SLASH).append(callDay).append(I_SLASH).toString();
            if (StringUtils.isNotBlank(rName) && rName.contains(callDate + telNum)) {
            } else {
                buffer.append(COMMA).append("录音名称格式不正确");
            }
            if (StringUtils.isNotBlank(rPath) && rPath.equals(checkPath + rName)) {
                checkFileExist(checkPath, rName, buffer, checkResult);
            } else {
                buffer.append(COMMA).append("录音路径格式不正确");
            }
        }
        checkString = buffer.toString();
        return StringUtils.isBlank(checkString) ? null : checkString;
    }

    /**
     * 检查录音文件是否存在
     *
     * @param filePath
     * @param buffer
     * @param checkResult
     */
    private void checkFileExist(String filePath, String rName, StringBuffer buffer, CheckResult checkResult) {
        String excelFilePath = checkResult.getFilePath().replace(SLASH, I_SLASH);
        String realFilePath;
        filePath = filePath.replace(SLASH, I_SLASH);
        if (excelFilePath.contains(filePath)) {
            String[] getPath = excelFilePath.split(filePath);
            realFilePath = getPath[0] + filePath + rName;
            File file = new File(realFilePath);
            if (!file.exists()) {
                buffer.append(COMMA).append("录音文件找不到，正确位置：").append(realFilePath);
            } else {
                checkResult.setCorrectSoundRecordNum(checkResult.getCorrectSoundRecordNum() + 1);
            }
        } else {
            buffer.append(COMMA).append("录音索引文件存放位置不对，正确存放位置需包含：").append(filePath);
        }
    }

    /**
     * 检查数字格式
     *
     * @param buffer
     * @param regexp
     * @param checkString
     * @param messages
     */
    private void checkNumFormat(StringBuffer buffer, String regexp, String checkString, String messages) {
        if (StringUtils.isNotBlank(checkString) && Pattern.matches(regexp, checkString)) {
        } else {
            buffer.append(COMMA).append(messages);
        }
    }

    /**
     * 校验所有字段
     *
     * @param t
     * @param <T>
     * @return
     */
    public static <T> List<String> validate(T t) {
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<T>> constraintViolations = validator.validate(t);
        List<String> messageList = new ArrayList<>();
        for (ConstraintViolation<T> constraintViolation : constraintViolations) {
            messageList.add(constraintViolation.getMessage());
        }
        return messageList;
    }
}
